﻿using Collector.Device;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace Collector.PulseFixture
{
    class FixtureCollector
    {
        private string TAG = "FixtureCollector:";        
        private CollectorState mCollectorState = CollectorState.eCOLLECTOR_STATE_IDLE;
        private USB3000DAQ mUSB3000Device = null;
        private int mSegmentMaxCount = 0;
        private uint mSegmentCurrentIndex = 0;
        private string mDeviceSerialNumber = "";
        // Unit Pa
        private int mBaseline = 0;
        // Unit Pa
        private int mTargetPressure = 0;
        private const int MAXMIN_QUEUE_LENGTH = 1000;
        // 治具传感器1波形数据队列
        private Queue<double> mQueueDAQAI0 = new Queue<double>();
        // 治具传感器2波形数据队列
        private Queue<double> mQueueDAQAI1 = new Queue<double>();

        // 存储通道0和通道1分段数据文件
        private string[] mDAQAI0RecordFile = new string[3];
        private string[] mDAQAI1RecordFile = new string[3];

        // value is fixture pressure, type - 0 is ai0 1 is ai1 channel        
        private Action<double, int> mDeliver;

        public int SegmentMaxCount
        {
            set
            {
                mSegmentMaxCount = value;
                mDAQAI0RecordFile = new string[mSegmentMaxCount];
                mDAQAI1RecordFile = new string[mSegmentMaxCount];
            }
            get { return mSegmentMaxCount; }
        }

        public uint SegmentCurrentIndex
        {
            set { mSegmentCurrentIndex = value; }
            get { return mSegmentCurrentIndex; }
        }

        public string DeviceSerialNumber
        {
            set { mDeviceSerialNumber = value; }
        }
           
        public int Baseline
        {
            set { mBaseline = value; }
            get { return mBaseline; }
        }

        public string[] DAQAI0RecordFile
        {
            get { return mDAQAI0RecordFile; }
        }

        public string[] DAQAI1RecordFile
        {
            get { return mDAQAI1RecordFile; }
        }

        public FixtureCollector()
        {
            mQueueDAQAI0.Clear();
            mQueueDAQAI1.Clear();
        }

        public void setFixtureDataDeliver(Action<double, int> deliver)
        {
            mDeliver = deliver;
        }

        public void setCollectorState(CollectorState state, int prod)
        {
            Log.Debug(TAG + "current state: {0} new state: {1}", mCollectorState, state);
            if (mCollectorState != state && state == CollectorState.eCOLLECTOR_STATE_START_TRIGGER)
            {
                // Clear to prepare next
                mQueueDAQAI0.Clear();
                mQueueDAQAI1.Clear();
                mSegmentCurrentIndex++;
                mDAQAI0RecordFile[mSegmentCurrentIndex-1] = createSaveRawDataFile("AI0");
                mDAQAI1RecordFile[mSegmentCurrentIndex-1] = createSaveRawDataFile("AI1");
            } 
            mCollectorState = state;
        }

        ~FixtureCollector()
        {
            stop();
            mDeliver = null;
            Log.Debug(TAG + "~FixtureCollector() destory");
        }

        public bool run()
        {
            if(initialization() == false)
            {
                return false;
            }

            // 开启数据采集卡
            mUSB3000Device.SmacqDAQData();

            return true;
        }

        public void stop()
        {
            if (null != mUSB3000Device)
            {

                mUSB3000Device.DAQReceived -= USBDAQ_Received;
                mUSB3000Device.ReceiveACK = false;
                mUSB3000Device.CloseDevice();
                mUSB3000Device = null;
                Log.Debug(TAG + "stop() USB3000 Device OK.");
            }

            mSegmentCurrentIndex = 0;
            mSegmentMaxCount = 0;
            mCollectorState = 0;
            mQueueDAQAI0.Clear();
            mQueueDAQAI1.Clear();
            mDAQAI0RecordFile = null;
            mDAQAI1RecordFile = null;            
        }

        private bool initialization()
        {
            if (mUSB3000Device != null)
            {
                return true;
            }

            mUSB3000Device = new USB3000DAQ();
            if (!mUSB3000Device.InitUSBDevices())
            {
                return false;
            }

            mUSB3000Device.DAQReceived += USBDAQ_Received;

            Log.Debug(TAG + "init() USB3000 Device OK.");
            return true;
        }

        private void USBDAQ_Received(DAQPortDataReciveEventArgs e)
        {
            float[] ai = e.ReceiveDAQData;
            float average;
            double pPData;
            double pressure;
            int i, j;

            for (j = 0; j < 2; j++)
            {
                average = 0;
                pPData = 0;
                for (i = 0; i < 125; i++)
                {
                    average = average + ai[j * 125 + i];
                }
                average = average / 125;
                if (j == 0)
                {
                    // average / 0.45 单位kPa, 乘以 1000 单位Pa
                    pressure = Math.Round((average / 0.45) * 1000, 6);
                    // mBar
                    pPData = pressure/100;

                    // 已经收到加压完成指令
                    if (mCollectorState == CollectorState.eCOLLECTOR_STATE_CAPTURING)
                    {
                        if (mQueueDAQAI0.Count < MAXMIN_QUEUE_LENGTH)
                        {
                            //mQueueDAQAI0.Dequeue();

                            mQueueDAQAI0.Enqueue(pPData);
                            // 转换成pa, 模拟传感器精度32转换系数，便于算法识别
                            int calibrated = (int)((pressure + mBaseline + mTargetPressure) * 32);
                            byte[] calibrated_byte = BitConverter.GetBytes(calibrated);

                            ByteToFile(calibrated_byte, mDAQAI0RecordFile[mSegmentCurrentIndex - 1]);
                        }
                    }                    
                }
                if (j == 1)
                {
                    // average / 0.45 单位kPa, 乘以 1000 单位Pa
                    pressure = Math.Round((average / 0.45) * 1000, 6);
                    // mBar
                    pPData = pressure / 100;

                    // 已经收到加压完成指令
                    if (mCollectorState == CollectorState.eCOLLECTOR_STATE_CAPTURING)
                    {
                        if (mQueueDAQAI1.Count < MAXMIN_QUEUE_LENGTH)
                        {
                            //mQueueDAQAI1.Dequeue();

                            mQueueDAQAI1.Enqueue(pPData);

                            // 转换成pa, 模拟传感器精度32转换系数，便于算法识别
                            int calibrated = (int)((pressure + mBaseline + mTargetPressure) * 32);
                            byte[] calibrated_byte = BitConverter.GetBytes(calibrated);


                            ByteToFile(calibrated_byte, mDAQAI1RecordFile[mSegmentCurrentIndex - 1]);
                        }
                    }
                }

                // 交付UI绘图
                mDeliver?.Invoke(pPData, j);
            }
        }

        public static bool ByteToFile(byte[] byteArray, string fileName)
        {
            bool result = false;
            byte[] header = { 0xbb, 0x66, 0xbb, 0x66, 0x06 };
            byte[] tail = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

            if(string.IsNullOrEmpty(fileName))
            {
                return false;
            }

            try
            {
                byte[] pressure = new byte[3];
                // Convert to little endpoint
                for (int m = 2; m >= 0; m--)
                {
                    pressure[2 - m] = byteArray[m];
                }

                using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write))
                {
                    fs.Write(header, 0, 5);
                    fs.Write(pressure, 0, pressure.Length);
                    fs.Write(tail, 0, tail.Length);
                    result = true;
                }
            }
            catch
            {
                result = false;
            }
            return result;
        }

        private string createSaveRawDataFile(string usbData = "AI0")
        {
            string rawDataPath = Application.StartupPath + "\\PulseData\\Segment";
            string strdate = DateTime.Now.ToString("yyyyMMdd");
            string str_hms = DateTime.Now.TimeOfDay.ToString("hhmmssfff");
            string logFileName = rawDataPath + "\\" + String.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}-{7}-{8}.dat",
                "GMMX", "00000000000", "4", mDeviceSerialNumber.Substring(4),
                strdate, str_hms,
                mBaseline,
                "Fixture1", usbData);

            Log.Debug(TAG + "CreateSaveRawDataFile() Save file path: " + logFileName);
            return logFileName;
        }
    }
}
